/***************************************************************************
 *   Copyright (C) 2005 by Christophe GONZALES and Pierre-Henri WUILLEMIN  *
 *   {prenom.nom}_at_lip6.fr                                                  *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include <agrum/learning/CountTree.h>

#ifdef GUM_NO_INLINE
#include <agrum/learning/CountTree.inl>
#endif /* GUM_NO_INLINE */

namespace gum {

	void CountTree::addParent(unsigned int parent)
	{	
		//__levels.resize(__levels.size()+1);
		ListBase<InstantiationBox *> * listParent =new ListBase<InstantiationBox *>();
		InstantiationBoxParent * parentN1;
		for(unsigned int i=0;i<__levels[__levels.size()-1]->size();++i)
		{
			parentN1=static_cast<InstantiationBoxParent*>(__levels[__levels.size()-1]->operator[](i));
//			unsigned int slist=static_cast<InstantiationBoxParent*>(__levels[i]->operator[](j)).size()
			unsigned int k=0;
			while(parentN1->hasChild(i))
//			for(unsigned int k=0;k<static_cast<InstantiationBoxParent*>(__levels[i]->operator[](j)).size();++k)
			{
				InstantiationBoxParent *parentC = new InstantiationBoxParent(__database.nbrModalities(parent));
				for(unsigned int n=0;n<__database.nbrModalities(parent);++n)
				{//Instantiation of children
					InstantiationBoxChild* child = new InstantiationBoxChild(__database.nbrModalities(__variables[__variables.size()-1]));
					parentC->addChild(n,*child);
				}
				for(unsigned int j=0;parentN1->dbCases(k).size();++j)
				{
					parentC->addCases(__database.value(parent,parentN1->dbCases(k)[j]), parentN1->dbCases(k)[j]);
					static_cast<InstantiationBoxChild*>(parentC->child(__database.value(parent,parentN1->dbCases(k)[j])))->increment(__database.value(__variables[__variables.size()-1],parentN1->dbCases(k)[j]));
				}
				parentN1->addChild(k,*parentC);				
				listParent->insert(parentC);
			}		
			parentN1->eraseDBCases();
		}
		setLeaves(*listParent);
		__levels.resize(__levels.size()+1);
		__levels[__levels.size()-1]=listParent;
	}//End AddParent

	void CountTree::replaceParent(unsigned int oldParent, unsigned int newParent)
	{
		if(findParent(newParent)==__variables.size())//NewParent not found in __variables
		{
			__variables[findParent(oldParent)]=newParent;
			eraseParent(findParent(newParent));
			for(unsigned int i=findParent(newParent);i<__variables.size()-2;++i)
				addParent(__variables[i]);
		}
	}//End Replace

	void CountTree::updateLeaves(InstantiationBox &child)
	{
		__leaves.insert(&child);
	}

	void CountTree::updateLevels(InstantiationBox &parent, unsigned int nbrParent)
	{
		__levels[nbrParent]->insert(&parent);
	}

	void CountTree::setLeaves(ListBase<InstantiationBox *> &parents)
	{
		__leaves.clear();
		unsigned k=0;
		for(unsigned int i=0; i<parents.size();++i)
		{
			k=0;
			while(static_cast<InstantiationBoxParent*>(parents[i])->hasChild(k))
			{
				__leaves.insert(static_cast<InstantiationBoxParent*>(parents[i])->child(k));
			}
		}
	}


}//End of namespace
